﻿using System;
using System.Diagnostics;
using Oxage.Common;

namespace Oxage.CNC
{
	public static class StopwatchExtensions
	{
		/// <summary>
		/// Measures how long it takes (how much ticks) to complete 1 millisecond.
		/// Value may vary between different CPUs and hardware configuration.
		/// </summary>
		/// <param name="milliseconds">How long to measure, value in milliseconds.</param>
		/// <returns></returns>
		public static int Measure(this Stopwatch stopwatch, int milliseconds)
		{
			long ticks = 0;
			Stopwatch sw = new Stopwatch();
			sw.Start();
			while (sw.ElapsedMilliseconds < milliseconds)
			{
				ticks++;
			}
			sw.Stop();
			return (int)(ticks / milliseconds);
		}

		/// <summary>
		/// Delays for the specified amount of microseconds. Tolerance varies from machine to machine but below 1% for 1000 microseconds.
		/// </summary>
		/// <param name="stopwatch"></param>
		/// <param name="microseconds">Number of microseconds to delay.</param>
		/// <remarks>
		/// Reference:
		/// http://stackoverflow.com/questions/1631501/need-microsecond-delay-in-net-app-for-throttling-udp-multicast-transmission-rate
		/// 
		/// Note: delays as low as 100 us are fairly accurate (approx. 1%), delays near 10 us are inacurate (approx. 30%).
		/// </remarks>
		public static void Sleep(this Stopwatch stopwatch, long microseconds)
		{
			if (!Stopwatch.IsHighResolution)
			{
				Logger.Log(new Exception("Cannot perform accurate timing!"));
			}

			long ticksPerSecond = Stopwatch.Frequency;
			long ticks = (ticksPerSecond / 1000000L) * microseconds;

			Stopwatch sw = new Stopwatch();
			sw.Start();

			long i = 0;
			while (sw.ElapsedTicks < ticks)
			{
				i++; //Do something
			}

			sw.Stop();
		}
	}
}
